package org.dromara.web.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jakarta.annotation.PreDestroy;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.domain.model.LoginUser;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.web.domain.Stock;
import org.dromara.web.domain.TPay;
import org.dromara.web.domain.bo.TPayBo;
import org.dromara.web.domain.vo.TPayVo;
import org.dromara.web.mapper.TPayMapper;
import org.dromara.web.service.TPayService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.*;
import java.util.List;

/**
 * <p>
 * 股票不是单点库存，不需要像电商一样防止超卖库存：
 * 股票数量在「整个市场」里流动，而不是你这台服务器本地维护。
 * 你的交易系统更多是一个「委托下单系统」，订单发到交易所，由交易所撮合成交。
 * </p>
 * <p>
 * 需要的控制点在账户层面：
 * 下单前检查 资金是否足够（买入时）
 * 下单前检查 持仓是否足够（卖出时）
 * </p>
 */
@Service
@RequiredArgsConstructor
public class TPayServiceImpl implements TPayService {


    private static final Logger log = LoggerFactory.getLogger(TPayServiceImpl.class);
    private final TPayMapper baseMapper;

    // 统一使用相对路径并确保目录存在
    // 推荐使用基于项目根目录的相对路径（更稳定）
    private final String rootPath = System.getProperty("user.dir"); // 获取当前工作目录
    private final File targetFile = new File(rootPath + "/ruoyi-admin/src/main/resources/userId.txt");

    /**
     * 查询支付信息
     *
     * @param id 主键
     * @return 支付信息
     */
    @Override
    public TPayVo queryById(Long id) {
        return baseMapper.selectVoById(id);
    }


    private LambdaQueryWrapper<TPay> buildQueryWrapper(TPayBo bo) {
        LambdaQueryWrapper<TPay> lqw = Wrappers.lambdaQuery();
        // 添加排序
        lqw.orderByAsc(TPay::getPayId);

        // 修改查询条件为可选参数
        lqw.eq(bo.getPayId() != null, TPay::getPayId, bo.getPayId());
        lqw.like(StringUtils.isNotBlank(bo.getOrderNo()), TPay::getOrderNo, bo.getOrderNo());
        lqw.eq(bo.getUserId() != null, TPay::getUserId, bo.getUserId()); // 修改为条件查询

        // 修复金额查询
        if (bo.getAmount() != null) {
            lqw.eq(TPay::getAmount, bo.getAmount()); // 直接使用BigDecimal比较
        }

        // 支付状态字段修正
        lqw.eq(StringUtils.isNotBlank(bo.getPayStatus()), TPay::getPayStatus, bo.getPayStatus());
        lqw.eq(StringUtils.isNotBlank(bo.getPayChannel()), TPay::getPayChannel, bo.getPayChannel());

        return lqw;
    }


    /**
     * 分页查询支付信息列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 支付信息分页列表
     */
    @Override
    public TableDataInfo<TPayVo> queryPageList(TPayBo bo, PageQuery pageQuery) {
        // 新增文件读取逻辑
        Long fileUserId = readUserIdFromFile();
        LambdaQueryWrapper<TPay> lqw = buildQueryWrapper(bo);
        if (fileUserId != null) {
            // 通过fileUserId作为查询条件查询数据库数据
            // 添加文件用户ID作为强制查询条件
            lqw.eq(TPay::getUserId, fileUserId);
            log.info("强制使用文件用户ID作为查询条件：{}", fileUserId);
            log.info("分页查询使用文件用户ID：{}", fileUserId);
        }

        Page<TPayVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询符合条件的支付信息列表
     *
     * @param bo 查询条件
     * @return 支付信息列表
     */
    @Override
    public List<TPayVo> queryList(TPayBo bo) {
        LambdaQueryWrapper<TPay> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    /**
     * 修改支付信息
     *
     * @param bo 支付信息
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean updateByBo(TPayBo bo) {
        // 新增文件读取逻辑
        Long fileUserId = readUserIdFromFile();
        // 如果fileUserId和bo中的支付id不一致，则返回false
        if (fileUserId != null && !fileUserId.equals(bo.getPayId())) {
            log.warn("文件用户ID和支付ID不一致，文件用户ID：{}，支付ID：{}", fileUserId, bo.getPayId());
            Exception e = new Exception("文件用户ID和支付ID不一致");
        }
        TPay update = MapstructUtils.convert(bo, TPay.class);
        return baseMapper.updateById(update) > 0;
    }


    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(Stock entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    // 新增文件读取方法
    private Long readUserIdFromFile() {
        String path = "D:\\code2\\stock-trading\\api\\ruoyi-admin\\src\\main\\resources\\userId.txt";
        try (BufferedReader reader = new BufferedReader(new FileReader(path))) {
            LoginUser loginUser = getLoginUser();
            if (ObjectUtil.isNotNull(loginUser)) {
                Long userId = loginUser.getUserId();
                // 依次读取文件中的所有userId并且比较和当前登录用户的userId是否一致，如果一致，则返回userId
                String line;
                // 判断当userId为1时，即为管理员，则返回null
                if (userId == 1) {
                    return null;
                }
                while ((line = reader.readLine()) != null) {
                    if (line.contains("userId = ")) {
                        String userIdStr = line.split("=")[1].trim();
                        if (userIdStr.equals(String.valueOf(userId))) {
                            return Long.parseLong(userIdStr);
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error("读取用户ID文件失败", e);
        }
        return null;
    }

    /**
     * 获取当前登录用户信息
     *
     * @return 当前登录用户的信息，如果用户未登录则返回 null
     */
    private LoginUser getLoginUser() {
        LoginUser loginUser;
        try {
            loginUser = LoginHelper.getLoginUser();
        } catch (Exception e) {
            log.warn("自动注入警告 => 用户未登录");
            return null;
        }
        return loginUser;
    }

    /**
     * 创建一个IO流对象，把userId.txt里面的内容清空
     * src/main/resources/userId.txt
     */

    @PreDestroy
    public void clearUserIdFile() {
        try (FileWriter writer = new FileWriter(targetFile, false)) {
            // 清空文件内容
            writer.write("");
            log.info("文件内容已清空");
        } catch (IOException e) {
            log.error("清空文件内容失败", e);
        }
    }
}
